import org.ws.edu.model.Answer;
import org.ws.edu.model.Question;
import org.ws.edu.model.Type;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Pribytkoyski Alexey
 */


/**
 * mode
 * 1 - choose test
 * 2 - testing
 * 3 - repeat mode
 * 4 - finish mode
 */

public class TestManager {
	private Socket socket = null;
	private ObjectInputStream in = null;
	private ObjectOutputStream out = null;
	private String[] testsList = null;
	private int mode = -1;
	private Type type = null;
	List<Answer> answerList = null;

	/**
	 * Начальная инициализация, получение сокета.
	 * @param sct - наш сокет
	 */
	public TestManager(Socket sct) {
		socket = sct;
		startSocket();
	}

	/**
	 * Стартуем сокеты
	 */
	private void startSocket() {
		try {
			in = new ObjectInputStream(socket.getInputStream());
			out = new ObjectOutputStream(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Получаем содержимое справки с сервера
	 * @return
	 */
	public String getHelp() {
		String[] help = null;
		String helpcorrect = null;
		try{
			out.writeInt(2);
			out.flush();
			help = (String[]) in.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		helpcorrect = help[0];
		for(int i = 1; i < help.length; i++) {
			helpcorrect += "\n" + help[i];
		}
		return helpcorrect;
	}

	/**
	 * Загружаем тесты (список валидных тестов)
	 */
	public String[] loadTestsList() {
		try {
			out.writeInt(0);
			out.flush();
			testsList = (String[]) in.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return testsList;
	}

	/**
	 * Получаем текущие режим программы. Ну а как, ведь надобно.
	 * @return - возвращаем режим
	 */
	public int getMode() {
		return mode;
	}

	/**
	 * При смене режима надо же его и установить для всей программы, что мы и делаем. Входной параметр - номер режима.
	 * @param mode - наш режим
	 */
	public void setMode(int mode) {
		this.mode = mode;
	}

	/**
	 * Получаем номер теста, с которым будем работать и говорим об этом серверу.
	 * И не медля получаем тип выбранного теста
	 * @param in - православный номер теста
	 */
	public void selectTest(String in) {
		int num = Integer.parseInt(in);
		try {
			out.writeObject(testsList[num]);
			out.flush();
			getType();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Собственно само получение типа теста
	 */
	private void getType() {
		try {
			type = (Type) in.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Получаем православную строку с вопросом и вариантами ответа
	 * @return - возвращаем ДА
	 */
	public String getQuestion() {
		return getQuestM2();
	}

	/**
	 * А вот тут получаем ответ от сервера, приводим к православному виду и отдаем тому, кто попросит
	 * @return - правильную строку, для вывода на форму
	 */
	private String getQuestM2() {
		String tmp = null;
		try {
			if (in.readBoolean()) {
				Question question = (Question) in.readObject();
				answerList = question.getAllAnswers();
				tmp = question.getName();
				for (int i = 0; i < answerList.size(); i++) {
					tmp += "\n" + String.valueOf(i + 1) + ". " + answerList.get(i).getName();
				}
				tmp += "\n\n" + "Введите 'pass' для пропуска вопроса. После мы вернёмся к нему автоматически";
			} else {
				if (mode == 2) {
					mode = 3;
					if (in.readBoolean()) {
						out.writeBoolean(true);
						out.flush();
						if(in.readBoolean()){
							Question question = (Question) in.readObject();
							answerList = question.getAllAnswers();
							tmp = question.getName();
							for (int i = 0; i < answerList.size(); i++) {
								tmp += "\n" + String.valueOf(i + 1) + ". " + answerList.get(i).getName();
							}
							tmp += "\n\n" + "Введите 'pass' для пропуска вопроса. После мы вернёмся к нему автоматически";
						}
					} else {
						mode = 4;
						tmp = (String) in.readObject();
						tmp += "\n\n" + "Вот ваш результат. Для выбора другого теста, кликните на кнопку, справа внизу";
					}
				} else  {
					mode = 4;
					tmp = (String) in.readObject();
					tmp += "\n\n" + "Вот ваш результат. Для выбора другого теста, кликните на кнопку, справа внизу";
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return tmp;
	}

	/**
	 * Отправляем православный ответ серверу на вопрос
	 * @param str - строка ответа, получанная с формы, неправильная
	 */
	public void setAnswer(String str) {
		try {
			out.writeObject(getUserAnswerFormatted(str));
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Даём сюда ответ пользователя, приводим к нужному виду и отдаём заказчику
	 * @param tmp - строка формы, временная
	 * @return возвращаем правильный вид ответа, для отправки на сервер
	 */
	private List<Answer> getUserAnswerFormatted(String tmp) {
		List<Answer> userAnswers = new ArrayList<Answer>();
		if (tmp.equals("pass")) {
			return userAnswers;
		}
		if (type.equals(Type.SCALES) || type.equals(Type.SINGLE_ANSWER_TEST)) {
			userAnswers.add(answerList.get(Integer.parseInt(tmp.trim()) - 1));
			return userAnswers;
		} else {
			String[] answersIndex = tmp.split(",");
			for (String s : answersIndex) {
				userAnswers.add(answerList.get(Integer.parseInt(s.trim()) - 1));
			}
		}
		return userAnswers;
	}
}
